home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / Libraries / PlayerPRO 4.5.1 / Plug-Ins / Import⁄Export Plugs / S3M2Mad.c < prev   
Text File  |  1996-02-06  |  28KB  |  1,057 lines

  1. /********************                        ***********************/
  2. //
  3. //    Player PRO 4.5x -- S3M to MADx
  4. //
  5. //    Version 2.0    - 12.3.95 ANR
  6. //
  7. //    To use with CodeWarrior 68K or PPC
  8. //
  9. //    Antoine ROSSET
  10. //    16 Tranchees
  11. //    1206 GENEVA
  12. //    SWITZERLAND
  13. //    
  14. //    FAX:            (+41 22) 346 11 97
  15. //    Compuserve:    100277,164
  16. //    Internet:         rosset@dial.eunet.ch
  17. //
  18. /********************                        ***********************/
  19.  
  20. #include "S3M.h"
  21. #include "MAD.h"
  22. #include "RDriver.h"
  23.  
  24. #if defined(powerc) || defined(__powerc)
  25. enum {
  26.         PlayerPROPlug = kCStackBased
  27.         | RESULT_SIZE(SIZE_CODE(sizeof(OSErr)))
  28.         | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof( OSType)))
  29.         | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof( Ptr*)))
  30.         | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof( MADPartition*)))
  31.         | STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof( PPInfoRec*)))
  32. };
  33.  
  34. ProcInfoType __procinfo = PlayerPROPlug;
  35. #else
  36. #include <A4Stuff.h>
  37. #endif
  38.  
  39. #define LOW(para) ((para) & 15)
  40. #define HI(para) ((para) >> 4)
  41.  
  42. unsigned long Tdecode32( void *msg_buf)
  43. {
  44.   unsigned char *buf = msg_buf;
  45.   
  46.   return( (unsigned long) buf[3] << 24) | ( (unsigned long) buf[2] << 16) | ( (unsigned long) buf[ 1] << 8) | ( (unsigned long) buf[0]);
  47. }
  48.  
  49. short Tdecode16( void *msg_buf)
  50. {
  51.   unsigned char *buf = msg_buf;
  52.   
  53.   return ( (short) buf[1] << 8) | ( (short) buf[0]);
  54. }
  55.  
  56. Cmd* GetMADCommand( register short PosX, register short    TrackIdX, register PatData*    tempMusicPat)
  57. {
  58.     if( PosX < 0) PosX = 0;
  59.     else if( PosX >= tempMusicPat->header.size) PosX = tempMusicPat->header.size -1;
  60.         
  61.     return( & (tempMusicPat->Cmds[ (tempMusicPat->header.size * TrackIdX) + PosX]));
  62. }
  63.  
  64. void pStrcpy(register unsigned char *s1, register unsigned char *s2)
  65. {
  66.     register short len, i;
  67.     
  68.     len = *s2;
  69.     for ( i = 0; i <= len; i++) s1[ i] = s2[ i];
  70. }
  71.  
  72. void ConvertS3MEffect( Byte B0, Byte B1, Byte *Cmd, Byte *Arg)
  73. {
  74.     Str255    tStr;
  75.     Byte        LoB1 = LOW( B1);
  76.     Byte        HiB1 = HI( B1);
  77.     
  78.     switch( B0 + 0x40)
  79.     {
  80.         default:    *Cmd = 0;            *Arg = 0;        break;
  81.         // Speed
  82.         case 'A':    *Cmd = speedE;        *Arg = B1;    break;
  83.         // Tempo
  84.         case 'T':    *Cmd = speedE;        *Arg = B1;    break;
  85.  
  86.         case 'B':    *Cmd = fastskipE;        *Arg = B1;    break;
  87.  
  88.         case 'C':    *Cmd = skipE;            *Arg = B1;    break;
  89.  
  90.         case 'D':
  91.             if( LoB1 == 0 || HiB1 == 0)        // Slide volume
  92.             {
  93.                 *Cmd = slidevolE;        *Arg = B1;
  94.             }
  95.             else if( HiB1 == 0x0F)        // Fine Slide volume DOWN
  96.             {
  97.                 *Cmd = extendedE;
  98.                 *Arg = 11 << 4;
  99.                 *Arg += LoB1;
  100.             }
  101.             else if( LoB1 == 0x0F)        // Fine Slide volume UP
  102.             {
  103.                 *Cmd = extendedE;
  104.                 *Arg = 10 << 4;
  105.                 *Arg += HiB1;
  106.             }
  107.         break;
  108.         
  109.         case 'E':
  110.             if( HiB1 == 0x0F)        // FineSlide DOWN
  111.             {
  112.                 *Cmd = extendedE;
  113.                 *Arg = 2 << 4;        //not supported
  114.                 *Arg += LoB1;
  115.             }
  116.             else if( HiB1 == 0x0E)    // ExtraFineSlide DOWN
  117.             {
  118.                 *Cmd = 0;            *Arg = 0;        //not supported
  119.             }
  120.             else                    // Slide DOWN
  121.             {
  122.                 *Cmd = upslideE;        *Arg = B1;
  123.             }
  124.         break;
  125.  
  126.         case 'F':
  127.             if( HiB1 == 0x0F)        // FineSlide UP
  128.             {
  129.                 *Cmd = extendedE;
  130.                 *Arg = 1 << 4;        //not supported
  131.                 *Arg += LoB1;
  132.             }
  133.             else if( HiB1 == 0x0E)    // ExtraFineSlide UP
  134.             {
  135.                 *Cmd = 0;            *Arg = 0;        //not supported
  136.             }
  137.             else                    // Slide UP
  138.             {
  139.                 *Cmd = downslideE;        *Arg = B1;
  140.             }
  141.         break;
  142.  
  143.         case 'G':    *Cmd = portamentoE;    *Arg = B1;    break;
  144.         case 'H':    *Cmd = vibratoE;        *Arg = B1;    break;
  145.         
  146.         case 'J':    *Cmd = arpeggioE;        *Arg = B1;    break;
  147.         case 'K':    *Cmd = vibratoslideE;    *Arg = B1;    break;
  148.         case 'L':    *Cmd = portaslideE;        *Arg = B1;    break;
  149.         case 'O':    *Cmd = offsetE;        *Arg = B1;    break;
  150.  
  151.         case 'S':        // Special Effects
  152.             switch( HiB1)
  153.             {
  154.                 default:    *Cmd = 0;        *Arg = 0;                            break;
  155.                 case 2:    *Cmd = extendedE;    *Arg = 5 << 4;        *Arg += LoB1;        break;    // FineTune
  156.                 case 3:    *Cmd = extendedE;    *Arg = 4 << 4;        *Arg += LoB1;        break;    // Set Vibrato WaveForm
  157.                 case 4:    *Cmd = extendedE;    *Arg = 7 << 4;        *Arg += LoB1;        break;    // Set Tremolo WaveForm
  158.                 case 0xB:    *Cmd = extendedE;    *Arg = 6 << 4;        *Arg += LoB1;        break;    // Loop pattern
  159.                 case 0xC:    *Cmd = extendedE;    *Arg = 12 << 4;    *Arg += LoB1;        break;    // Cut sample
  160.                 case 0xD:    *Cmd = extendedE;    *Arg = 13 << 4;    *Arg += LoB1;        break;    // Delay sample
  161.                 case 0xE:    *Cmd = extendedE;    *Arg = 14 << 4;    *Arg += LoB1;        break;    // Delay pattern
  162.             }
  163.         break;
  164.     }
  165. }
  166.  
  167. void ConvertMADEffect( Byte Cmd, Byte Arg, Byte *B0, Byte *B1)
  168. {
  169.     *B0 = 0;
  170.     *B1 = 0;
  171.  
  172.     switch( Cmd)
  173.     {
  174.         case speedE:        *B0 = 'A' - 0x40;    *B1 = Arg;    break;
  175.         case fastskipE:        *B0 = 'B' - 0x40;    *B1 = Arg;    break;
  176.         case skipE:        *B0 = 'C' - 0x40;    *B1 = Arg;    break;
  177.         case slidevolE:        *B0 = 'D' - 0x40;    *B1 = Arg;    break;
  178.         case upslideE:        *B0 = 'E' - 0x40;    *B1 = Arg;    break;
  179.         case downslideE:    *B0 = 'F' - 0x40;    *B1 = Arg;    break;
  180.         case portamentoE:    *B0 = 'G' - 0x40;    *B1 = Arg;    break;
  181.         case vibratoE:        *B0 = 'H' - 0x40;    *B1 = Arg;    break;
  182.         
  183.         case arpeggioE:        *B0 = 'J' - 0x40;    *B1 = Arg;    break;
  184.         case vibratoslideE:    *B0 = 'K' - 0x40;    *B1 = Arg;    break;
  185.         case portaslideE:    *B0 = 'L' - 0x40;    *B1 = Arg;    break;
  186.         case offsetE:        *B0 = 'O' - 0x40;    *B1 = Arg;    break;
  187.         
  188.         case extendedE:
  189.             switch( (Arg & 0xF0) >> 4)
  190.             {
  191.                 case 1:    *B0 = 'F' - 0x40;    *B1 = 0xf0 + (Arg & 0x0F);        break;
  192.                 case 2:    *B0 = 'E' - 0x40;    *B1 = 0xf0 + (Arg & 0x0F);        break;
  193.                 
  194.                 case 5:    *B0 = 'S' - 0x40;    *B1 = 0x20 + (Arg & 0x0F);        break;
  195.                 
  196.                 case 4:    *B0 = 'S' - 0x40;    *B1 = 0x30 + (Arg & 0x0F);        break;
  197.                 case 7:    *B0 = 'S' - 0x40;    *B1 = 0x40 + (Arg & 0x0F);        break;
  198.                 case 6:    *B0 = 'S' - 0x40;    *B1 = 0xb0 + (Arg & 0x0F);        break;
  199.                 case 12:    *B0 = 'S' - 0x40;    *B1 = 0xc0 + (Arg & 0x0F);        break;
  200.                 case 13:    *B0 = 'S' - 0x40;    *B1 = 0xd0 + (Arg & 0x0F);        break;
  201.                 case 14:    *B0 = 'S' - 0x40;    *B1 = 0xe0 + (Arg & 0x0F);        break;
  202.                 
  203.                 case 11:    *B0 = 'D' - 0x40;    *B1 = 0xf0 + (Arg & 0x0F);        break;
  204.                 case 10:    *B0 = 'D' - 0x40;    *B1 = 0x0f + ((Arg & 0x0F)<<4);    break;
  205.             }
  206.         break;
  207.     }
  208. }
  209.  
  210. Ptr    ConvertMad2S3M( MADPartition *theMAD)
  211. {
  212.     short             i, x, z, maxInstru;
  213.     Ptr                finalS3M, finalS3MCopy, maxfinalS3M;
  214.     long                InstruSize;
  215.     long                NoIns;
  216.     long                genHeaderSize;
  217.     s3minsform        *ins[ 64];
  218.     Cmd                *aCmd;
  219.     long                PatternSize;
  220.     
  221.     s3mform            *s3minfo;
  222.     
  223.     unsigned short        *parapins;
  224.     unsigned short        *parappat;
  225.     
  226.     /********************************/
  227.     /*             MAD INFORMATIONS               */
  228.     /********************************/
  229.     InstruSize = 0;
  230.     PatternSize = 0;
  231.     NoIns = 0;
  232.     for( i = 0; i < 64 ; i++)
  233.     {
  234.         if( theMAD->header->fid[ i].numSamples > 0)
  235.         {
  236.             InstruSize            += 16 + theMAD->sample[ i][ 0]->size;
  237.             //NoIns++;
  238.             
  239.             NoIns = i+1;
  240.         }
  241.     }
  242.     
  243.     for( i = 0; i < theMAD->header->numPat;i++)
  244.     {
  245.         PatternSize += 6L * theMAD->header->numChn * theMAD->partition[ i]->header.size;
  246.         PatternSize += 16;
  247.     }
  248.     /********************************/
  249.     
  250.     
  251.     finalS3MCopy = finalS3M = NewPtr(         sizeof( s3mform) +
  252.                                     theMAD->header->numPointers +
  253.                                     NoIns*2 +
  254.                                     theMAD->header->numPat*2 +
  255.                                     sizeof(s3minsform) * NoIns +
  256.                                     InstruSize + 
  257.                                     PatternSize);
  258.     maxfinalS3M = finalS3M + GetPtrSize( finalS3M);
  259.     if( finalS3M == 0L) return 0L;
  260.     
  261.     
  262.     
  263.     
  264.     /********************************/
  265.     /* s3minfo -- s3minfo -- s3minfo -- s3minfo -- */
  266.     /********************************/
  267.     {
  268.         s3minfo = (s3mform*) finalS3MCopy;
  269.     
  270.         strncpy( s3minfo->name, theMAD->header->name, 28);
  271.         s3minfo->sig1             = 26;
  272.         s3minfo->type            = 16;
  273.         s3minfo->sig2[ 0] = s3minfo->sig2[ 1] = 0;
  274.         
  275.         s3minfo->ordernum        =    theMAD->header->numPointers;        s3minfo->ordernum = Tdecode16(  &s3minfo->ordernum);
  276.         s3minfo->insnum        =     NoIns;                            s3minfo->insnum = Tdecode16(  &s3minfo->insnum);
  277.         s3minfo->patnum        =    theMAD->header->numPat;            s3minfo->patnum = Tdecode16(  &s3minfo->patnum);
  278.         
  279.         s3minfo->flags            =    0;
  280.         s3minfo->cwtv            =    0x2013;
  281.         s3minfo->ffv            =    1;                                s3minfo->ffv = Tdecode16(  &s3minfo->ffv);
  282.         
  283.         
  284.         strncpy( s3minfo->s3msig, "SCRM", 4);
  285.         
  286.         s3minfo->mastervol        =     64;
  287.         s3minfo->initialspeed    =    theMAD->header->speed;
  288.         s3minfo->initialtempo    =    theMAD->header->tempo;
  289.         s3minfo->mastermul        =    0x30;
  290.         
  291.         for( i = 0; i < 12; i++) s3minfo->sig3[ i] = 0;
  292.         
  293.         for( i = 0; i < 16; i++) s3minfo->chanset[ i] = i;
  294.         for( i = 16; i < 32; i++) s3minfo->chanset[ i] = 255;
  295.         
  296.         finalS3MCopy += 96;
  297.     }
  298.     if( finalS3MCopy >= maxfinalS3M) Debugger();
  299.     
  300.     /********************************/
  301.     /*     orders -- orders -- orders -- orders      */
  302.     /********************************/
  303.     {
  304.         unsigned char    *orders;
  305.     
  306.         orders = (unsigned char *) finalS3MCopy;
  307.         for( i = 0; i < theMAD->header->numPointers; i++)
  308.         {
  309.             orders[ i] = theMAD->header->oPointers[ i];        orders[ i] = Tdecode16(  &orders[ i]);
  310.         }
  311.         finalS3MCopy += theMAD->header->numPointers;
  312.     }
  313.     if( finalS3MCopy >= maxfinalS3M) Debugger();
  314.     /********************************/
  315.     /*     Ins Num -- Ins Num -- Ins Num -- Ins Num      */
  316.     /********************************/
  317.     {
  318.         parapins = (unsigned short *) finalS3MCopy;
  319.         
  320.         for( i = 0; i < NoIns; i++) parapins[ i] = 0;
  321.         finalS3MCopy += NoIns*2L;
  322.     }
  323.     if( finalS3MCopy >= maxfinalS3M) Debugger();
  324.     /********************************/
  325.     /*     Pat Num -- Pat Num -- Pat Num -- Pat Num */
  326.     /********************************/
  327.     {
  328.         parappat = (unsigned short *) finalS3MCopy;
  329.         
  330.         for( i = 0; i < theMAD->header->numPat; i++) parappat[ i] = 0;
  331.         finalS3MCopy += theMAD->header->numPat*2L;
  332.     }
  333.     if( finalS3MCopy >= maxfinalS3M) Debugger();
  334.     
  335.     /*********************************/
  336.     /*     Ins Form -- Ins Form -- Ins Form -- Ins Form */
  337.     /*********************************/
  338.     for (i = 0; i < NoIns; i++)
  339.     {
  340.         if( theMAD->header->fid[ i].numSamples > 0)
  341.         {
  342.             sData        *curData = theMAD->sample[ i][ 0];
  343.             
  344.             parapins[ i] =  (16L + finalS3MCopy - finalS3M) / 16L;
  345.             finalS3MCopy = finalS3M + parapins[ i]*16L;
  346.             parapins[ i] = Tdecode16(  ¶pins[ i]);
  347.             
  348.             /**/
  349.             
  350.             ins[ i] = (s3minsform*) finalS3MCopy;
  351.             
  352.             ins[ i]->instype                =    1;
  353.             strncpy( (Ptr) ins[ i]->insdosname, theMAD->header->fid[i].name, 12);
  354.             ins[ i]->inssig1                =    0;
  355.             ins[ i]->insmemseg            =    0;
  356.             ins[ i]->inslength            =    curData->size;                        ins[ i]->inslength = Tdecode32( &ins[ i]->inslength);
  357.             ins[ i]->insloopbeg            =    curData->loopBeg;                    ins[ i]->insloopbeg = Tdecode32( &ins[ i]->insloopbeg);
  358.             ins[ i]->insloopend            =    curData->loopBeg + curData->loopSize;    ins[ i]->insloopend = Tdecode32( &ins[ i]->insloopend);
  359.             ins[ i]->insvol                =    curData->vol;
  360.             ins[ i]->insdsk                =    0;
  361.             ins[ i]->inspack                =    0;
  362.             
  363.             ins[ i]->insflags            =     0;
  364.             if( curData->loopSize != 0)     ins[ i]->insflags += 1;
  365.             if( curData->amp == 16)         ins[ i]->insflags += 4;
  366.             
  367.             ins[ i]->insloc2spd            =    curData->c2spd;                    ins[ i]->insloc2spd = Tdecode16(  &ins[ i]->insloc2spd);
  368.             ins[ i]->inshic2spd            =    0;
  369.             for( x = 0; x < 4; x++)        ins[ i]->inssig2[ x] = 0;
  370.             ins[ i]->insgvspos            =    256;                                ins[ i]->insgvspos = Tdecode16(  &ins[ i]->insgvspos);
  371.             ins[ i]->insint512            =    0;                                ins[ i]->insint512 = Tdecode16(  &ins[ i]->insint512);
  372.             ins[ i]->insintlastused        =    0;
  373.             strncpy( (Ptr) ins[ i]->insname, theMAD->header->fid[i].name, 28);
  374.             ins[ i]->inssig                =    'SCRS';
  375.         }
  376.         else
  377.         {
  378.             parapins[ i] =  (16L + finalS3MCopy - finalS3M) / 16L;
  379.             finalS3MCopy = finalS3M + parapins[ i]*16L;
  380.             parapins[ i] = Tdecode16(  ¶pins[ i]);
  381.             
  382.             /**/
  383.             
  384.             ins[ i] = (s3minsform*) finalS3MCopy;
  385.             
  386.             ins[ i]->instype                =    0;
  387.             strncpy( (Ptr) ins[ i]->insdosname, theMAD->header->fid[i].name, 12);
  388.             ins[ i]->inssig1                =    0;
  389.             ins[ i]->insmemseg            =    0;
  390.             ins[ i]->inslength            =    0;
  391.             ins[ i]->insloopbeg            =    0;
  392.             ins[ i]->insloopend            =    0;
  393.             ins[ i]->insvol                =    0;
  394.             ins[ i]->insdsk                =    0;
  395.             ins[ i]->inspack                =    0;
  396.             
  397.             ins[ i]->insflags            =     0;
  398.             
  399.             ins[ i]->insloc2spd            =    NOFINETUNE;                        ins[ i]->insloc2spd = Tdecode16(  &ins[ i]->insloc2spd);
  400.             ins[ i]->inshic2spd            =    0;
  401.             for( x = 0; x < 4; x++)        ins[ i]->inssig2[ x] = 0;
  402.             ins[ i]->insgvspos            =    256;    
  403.             ins[ i]->insint512            =    0;
  404.             ins[ i]->insintlastused        =    0;
  405.             strncpy( (Ptr) ins[ i]->insname, theMAD->header->fid[i].name, 28);
  406.             ins[ i]->inssig                =    0;
  407.         }
  408.         /**/
  409.         
  410.         finalS3MCopy += sizeof(s3minsform);
  411.     }
  412.     if( finalS3MCopy >= maxfinalS3M) Debugger();
  413.     /*********************************/
  414.     /*     Sample Data -- Sample Data -- Sample Data   */
  415.     /*********************************/
  416.     
  417.     for (i = 0; i < NoIns; i++)
  418.     {
  419.         if( theMAD->header->fid[ i].numSamples > 0)
  420.         {
  421.             sData        *curData = theMAD->sample[ i][ 0];
  422.             
  423.             ins[ i]->insmemseg = (16L + finalS3MCopy - finalS3M) / 16L;
  424.             finalS3MCopy = finalS3M + ins[ i]->insmemseg*16L;
  425.             ins[ i]->insmemseg = Tdecode16(  &ins[ i]->insmemseg);
  426.             
  427.             BlockMove( curData->data, finalS3MCopy, curData->size);
  428.             finalS3MCopy += curData->size;
  429.         }
  430.     }
  431.     if( finalS3MCopy >= maxfinalS3M) Debugger();
  432.     /*********************************/
  433.     /*     Pattern Data -- Pattern Data -- Pattern Data */
  434.     /*********************************/
  435.     
  436.     for (i = 0; i < theMAD->header->numPat; i++)
  437.     {
  438.         long Row = 0;
  439.     
  440.         parappat[ i] = (16L + finalS3MCopy - finalS3M) / 16L;
  441.         finalS3MCopy = finalS3M + parappat[ i]*16L;
  442.         parappat[ i] = Tdecode16(  ¶ppat[ i]);
  443.         
  444.         finalS3MCopy++;
  445.         
  446.         while( Row < 64)
  447.         {
  448.             for( z = 0; z < theMAD->header->numChn; z++)
  449.             {
  450.                 Byte        *tempChar = (Byte*) finalS3MCopy;
  451.                 
  452.                 aCmd = GetMADCommand( Row, z, theMAD->partition[ i]);
  453.                 
  454.                 if(     aCmd->note        != 0xFF ||
  455.                     aCmd->ins            != 0 ||
  456.                     aCmd->cmd        != 0 ||
  457.                     aCmd->arg        != 0 ||
  458.                     aCmd->vol        != 0xFF)
  459.                     {
  460.                         *tempChar = 0;
  461.                         
  462.                         finalS3MCopy++;
  463.                         
  464.                         // Channel
  465.                         
  466.                         *tempChar    = z;
  467.                         
  468.                         // PERIOD
  469.                         
  470.                         if( aCmd->note != 0xFF || aCmd->ins != 0)
  471.                         {
  472.                             short Octave, Note;
  473.                         
  474.                             *tempChar += 32;
  475.                             
  476.                             if( aCmd->note == 0xFF)
  477.                             {
  478.                                 finalS3MCopy[ 0] = 0xFF;
  479.                             }
  480.                             else
  481.                             {
  482.                                 Octave = aCmd->note / 12;
  483.                                 Note = aCmd->note - Octave*12;
  484.                                 
  485.                                 finalS3MCopy[ 0] = Octave << 4;
  486.                                 finalS3MCopy[ 0] += Note;
  487.                             }
  488.                             
  489.                             finalS3MCopy[ 1] = aCmd->ins;
  490.                             finalS3MCopy += 2L;
  491.                         }
  492.                         
  493.                         // VOLUME
  494.                         
  495.                         if( aCmd->vol != 0xFF || aCmd->cmd == volumeE)
  496.                         {
  497.                             *tempChar += 64;
  498.                             
  499.                             if( aCmd->cmd == volumeE) finalS3MCopy[ 0] = aCmd->arg;
  500.                             else finalS3MCopy[ 0] = aCmd->vol - 0x10;
  501.                             
  502.                             finalS3MCopy += 1L;
  503.                         }
  504.                         
  505.                         // PARAMETER
  506.                         
  507.                         if( aCmd->cmd != 0 || aCmd->arg != 0)
  508.                         {
  509.                             *tempChar += 128;
  510.                             
  511.                             ConvertMADEffect( aCmd->cmd, aCmd->arg, (Byte*) &finalS3MCopy[ 0], (Byte*) &finalS3MCopy[ 1]);
  512.                             
  513.                             finalS3MCopy += 2L;
  514.                         }
  515.                     }
  516.             }
  517.             
  518.             *finalS3MCopy = 0;    // end of row
  519.             finalS3MCopy++;
  520.             Row++;
  521.         }
  522.         if( finalS3MCopy >= maxfinalS3M) Debugger();
  523.     }
  524.     
  525.     SetPtrSize( finalS3M, finalS3MCopy - finalS3M);
  526.     
  527.     return( (Ptr) finalS3M);
  528. }
  529.  
  530. OSErr ConvertS3M2Mad( Ptr    theS3M, long MODSize, MADPartition *theMAD)
  531. {
  532.     long                 i, PatMax, x, z, channel, Row;
  533.     long                 sndSize, OffSetToSample, OldTicks, temp, starting;
  534.     Ptr                MaxPtr;
  535.     OSErr            theErr;
  536.     Ptr                theInstrument[ 64], destPtr;
  537.     Byte                tempChar, *theS3MCopy;
  538.     short            Note, Octave, maxTrack;
  539.     short            S3Mperiod[ 12] = {1712,1616,1524,1440,1356,1280,1208,1140,1076,1016, 960, 907};
  540.     long                note_st3period;
  541.     long                note_amigaperiod;
  542.     Byte                *ChannelSettings;
  543.     
  544.     /**** Variables pour le MAD ****/
  545.     Cmd                *aCmd;
  546.  
  547.     /**** Variables pour le S3M ****/
  548.     
  549.     s3mform            s3minfo;
  550.     /********************************/
  551.  
  552.     for( i = 0 ; i < 64; i ++)
  553.     {
  554.         theInstrument[ i] = 0L;
  555.     }
  556.  
  557.     /**** Header principal *****/
  558.     theS3MCopy = (Byte*) theS3M;
  559.     BlockMove( theS3MCopy, &s3minfo, 96);
  560.     theS3MCopy += 96;
  561.     
  562.     s3minfo.ordernum    = Tdecode16(  &s3minfo.ordernum);
  563.     s3minfo.insnum        = Tdecode16(  &s3minfo.insnum);
  564.     s3minfo.patnum        = Tdecode16(  &s3minfo.patnum);
  565.     s3minfo.flags        = Tdecode16(  &s3minfo.flags);
  566.     s3minfo.cwtv        = Tdecode16(  &s3minfo.cwtv);
  567.     s3minfo.ffv        = Tdecode16(  &s3minfo.ffv);
  568.  
  569.     /**** Order Num *****/
  570.     s3minfo.orders = (unsigned char *) NewPtr( s3minfo.ordernum);
  571.     BlockMove( theS3MCopy, s3minfo.orders, s3minfo.ordernum);
  572.     theS3MCopy += s3minfo.ordernum;
  573.     
  574.     /**** Ins Num *****/
  575.     s3minfo.parapins = (unsigned short *) NewPtr( s3minfo.insnum * 2L);
  576.     BlockMove( theS3MCopy, s3minfo.parapins, s3minfo.insnum * 2L);
  577.     theS3MCopy += s3minfo.insnum * 2L;
  578.     for( i = 0; i < s3minfo.insnum; i++)
  579.     {
  580.         s3minfo.parapins[ i] = Tdecode16(  &s3minfo.parapins[ i]);
  581.     }
  582.     
  583.     
  584.     /**** Pat Num *****/
  585.     s3minfo.parappat = (unsigned short *) NewPtr( s3minfo.patnum * 2L);
  586.     BlockMove( theS3MCopy, s3minfo.parappat, s3minfo.patnum * 2L);
  587.     theS3MCopy += s3minfo.patnum * 2L;
  588.     for( i = 0; i < s3minfo.patnum; i++)
  589.     {
  590.         s3minfo.parappat[ i] = Tdecode16(  &s3minfo.parappat[ i]);
  591.     }
  592.  
  593.     /**** Ins Data ****/
  594.     if( s3minfo.insnum > 64) s3minfo.insnum = 64;
  595.     s3minfo.insdata = (s3minsform *) NewPtr( sizeof(s3minsform) * s3minfo.insnum);
  596.     for (i = 0; i < s3minfo.insnum; i++)
  597.     {
  598.         theInstrument[ i] = 0L;
  599.     
  600.         theS3MCopy = (Byte*) theS3M;
  601.         theS3MCopy += s3minfo.parapins[i]*16L;
  602.         
  603.         BlockMove( theS3MCopy, &s3minfo.insdata[i], sizeof(s3minsform));
  604.         
  605.         s3minfo.insdata[i].insmemseg        = Tdecode16( &s3minfo.insdata[i].insmemseg);
  606.         s3minfo.insdata[i].inslength        = Tdecode32( &s3minfo.insdata[i].inslength);
  607.         
  608.         if( s3minfo.insdata[i].insflags&1)
  609.         {
  610.             s3minfo.insdata[i].insloopbeg        = Tdecode32( &s3minfo.insdata[i].insloopbeg);
  611.             s3minfo.insdata[i].insloopend        = Tdecode32( &s3minfo.insdata[i].insloopend);
  612.         }
  613.         else
  614.         {
  615.             s3minfo.insdata[i].insloopbeg        = 0;
  616.             s3minfo.insdata[i].insloopend        = 0;
  617.         }
  618.         
  619.         s3minfo.insdata[i].insloc2spd        = Tdecode16(  &s3minfo.insdata[i].insloc2spd);
  620.         s3minfo.insdata[i].inshic2spd        = Tdecode16(  &s3minfo.insdata[i].inshic2spd);
  621.         s3minfo.insdata[i].insgvspos        = Tdecode16(  &s3minfo.insdata[i].insgvspos);
  622.         s3minfo.insdata[i].insint512        = Tdecode16(  &s3minfo.insdata[i].insint512);
  623.         s3minfo.insdata[i].insintlastused    = Tdecode32( &s3minfo.insdata[i].insintlastused);
  624.         
  625.         if (s3minfo.insdata[i].instype == 1 && s3minfo.insdata[i].inspack == 0 && s3minfo.insdata[i].inssig == 'SCRS')
  626.             {
  627.                 theS3MCopy = (Byte*) theS3M;
  628.                 theS3MCopy += s3minfo.insdata[i].insmemseg*16L;
  629.                 
  630.                 theInstrument[ i] = (Ptr) theS3MCopy;
  631.             }
  632.             else
  633.             {
  634.                 theInstrument[ i] = 0L;
  635.             }
  636.     }
  637.  
  638.     /******** Le S3M a été lu et analysé ***********/
  639.     /******** Copie des informations dans le MAD ***/
  640.     
  641.     theMAD->header = (MADSpec*) NewPtrClear( sizeof( MADSpec));    
  642.     theMAD->header->MAD = 'MADH';
  643.     for(i=0; i<32; i++) theMAD->header->name[i] = 0;
  644.     for(i=0; i<28; i++) theMAD->header->name[i] = s3minfo.name[i];
  645.  
  646.     theMAD->header->numPat        = s3minfo.patnum;
  647.     theMAD->header->numPointers    = s3minfo.ordernum;
  648.     theMAD->header->speed        = s3minfo.initialspeed;
  649.     theMAD->header->tempo        = s3minfo.initialtempo;
  650.     
  651.     for(i=0; i<128; i++) theMAD->header->oPointers[ i] = 0;
  652.     for(i=0; i<s3minfo.ordernum; i++)
  653.     {
  654.         theMAD->header->oPointers[ i] = s3minfo.orders[i];
  655.         
  656.         if( theMAD->header->oPointers[ i] < 0 || theMAD->header->oPointers[ i] >= s3minfo.patnum) theMAD->header->oPointers[ i] = 0;
  657.     }
  658.  
  659.     /********************/
  660.     /***** INSTRUMENTS *****/
  661.     /********************/
  662.  
  663.     for(i  = 0 ; i < MAXINSTRU; i++)
  664.     {
  665.         for( x = 0; x < MAXSAMPLE; x++) theMAD->sample[ i][ x] = 0L;
  666.  
  667.         theMAD->header->fid[i].numSamples    = 0;
  668.     }
  669.  
  670.     for(i=0; i<s3minfo.insnum; i++)
  671.     {
  672.         InstrData        *curIns = &theMAD->header->fid[ i];
  673.         
  674.         curIns->type    = 0;
  675.         
  676.         if( theInstrument[ i] != 0L)
  677.         {
  678.             sData    *curData;
  679.  
  680.             curIns->numSamples = 1;
  681.             
  682.  
  683.             curData = theMAD->sample[ i][ 0] = (sData*) NewPtrClear( sizeof( sData));
  684.             
  685.             curData->size        = s3minfo.insdata[i].inslength;
  686.             curData->loopBeg     = s3minfo.insdata[i].insloopbeg;
  687.             curData->loopSize     = s3minfo.insdata[i].insloopend - s3minfo.insdata[i].insloopbeg;
  688.             curData->vol        = s3minfo.insdata[i].insvol;
  689.             curData->c2spd        = s3minfo.insdata[i].insloc2spd;
  690.             curData->loopType    = 0;
  691.             curData->amp        = 8;        if( s3minfo.insdata[i].insflags&4)    curData->amp        = 16;
  692.             curData->panning    = 0;
  693.             curData->relNote    = 0;
  694.             for( x = 0; x < 28; x++) curData->name[ x] = s3minfo.insdata[i].insname[x];
  695.             
  696.             curData->data         = NewPtr( curData->size);
  697.             if( curData->data == 0L) DebugStr("\pInstruments: I NEED MEMORY !!! NOW !");
  698.             
  699.             if( curData->data != 0L)
  700.             {
  701.                 BlockMove( theInstrument[i], curData->data, curData->size);
  702.                 
  703.                 if( s3minfo.ffv != 1)
  704.                 {
  705.                     for( temp = 0; temp < curData->size; temp++) *(curData->data + temp) -= 0x80;
  706.                 }
  707.             }
  708.         }
  709.         else curIns->numSamples = 0;
  710.     }
  711.     /********************/
  712.     
  713.     /*********************/
  714.     /*           Check MaxTrack         */
  715.     /*********************/
  716.     maxTrack = 0;
  717.     for( i = 0; i < theMAD->header->numPat ; i++)
  718.     {
  719.         Row = 0;
  720.         
  721.         if( s3minfo.parappat[ i] > 0)
  722.         {
  723.             theS3MCopy = (Byte*) theS3M;
  724.             theS3MCopy += ( (long) s3minfo.parappat[i] )*16L;
  725.             theS3MCopy++;
  726.             
  727.             while( Row < 64)
  728.             {
  729.                 tempChar = *theS3MCopy;
  730.                 theS3MCopy++;
  731.                 
  732.                 if( tempChar == 0) Row++;
  733.                 else
  734.                 {    // Channel
  735.                     channel = tempChar;
  736.                     channel &= 31;
  737.                     
  738.                     if( channel > maxTrack) maxTrack = channel;
  739.                     if( (tempChar & 32) != 0) theS3MCopy += 2L;
  740.                     if( (tempChar & 64) != 0) theS3MCopy += 1L;
  741.                     if( (tempChar & 128) != 0) theS3MCopy += 2L;
  742.                 }
  743.             }
  744.         }
  745.     }
  746.     maxTrack ++;
  747.     
  748.     
  749.     /** Pair **/
  750.     maxTrack++;
  751.     maxTrack /= 2;
  752.     maxTrack *= 2;
  753.     /********************/
  754.     /***** TEMPORAIRE ******/
  755.     /********************/
  756.     
  757.     theMAD->header->numChn = maxTrack;
  758.     
  759.     starting = 0;
  760.  
  761.     for( i = 0; i < MAXPATTERN; i++) theMAD->partition[ i] = 0L;
  762.     for( i = 0; i < theMAD->header->numPat ; i++)
  763.     {
  764.         theMAD->partition[ i] = (PatData*) NewPtrClear( sizeof( PatData) + theMAD->header->numChn * 64L * sizeof( Cmd));
  765.         if( theMAD->partition[ i] == 0L) return MADNeedMemory;
  766.         
  767.         theMAD->partition[ i]->header.size = 64L;
  768.         theMAD->partition[ i]->header.compMode = 'NONE';
  769.         
  770.         for( x = 0; x < 20; x++) theMAD->partition[ i]->header.name[ x] = 0;
  771.     
  772.         theMAD->partition[ i]->header.patBytes = 0L;
  773.         theMAD->partition[ i]->header.unused2 = 0L;
  774.     
  775.         MaxPtr = (Ptr) theMAD->partition[ i];
  776.         MaxPtr += sizeof( PatData) + theMAD->header->numChn * 64L * sizeof( Cmd);
  777.         
  778.         for( Row = 0; Row < 64; Row++)
  779.         {
  780.             for(z = 0; z < theMAD->header->numChn; z++)
  781.             {
  782.                 aCmd = GetMADCommand( Row, z, theMAD->partition[ i]);
  783.                 
  784.                 aCmd->note        = 0xFF;
  785.                 aCmd->ins            = 0;
  786.                 aCmd->cmd        = 0;
  787.                 aCmd->arg        = 0;
  788.                 aCmd->vol        = 0xFF;
  789.             }
  790.         }
  791.         
  792.         if( s3minfo.parappat[ i] > 0)
  793.         {
  794.             theS3MCopy = (Byte*) theS3M;
  795.             theS3MCopy += ( (long) s3minfo.parappat[i] )*16L;
  796.             theS3MCopy++;
  797.             
  798.             Row = 0;
  799.             while( Row < 64)
  800.             {
  801.                 /*
  802.                     BYTE:flag,     0        =    end of row
  803.                                 &31        =    channel
  804.                                 &32        =    follows;  BYTE:note, BYTE:instrument
  805.                                 &64        =    follows;  BYTE:volume
  806.                                 &128    =    follows; BYTE:command, BYTE:info
  807.                 */
  808.                     
  809.                     tempChar = *theS3MCopy;
  810.                     theS3MCopy++;
  811.     
  812.                     if( tempChar == 0) Row++;
  813.                     else
  814.                     {
  815.                         // Channel
  816.                         
  817.                         channel = tempChar;
  818.                         channel &= 31;
  819.                         if( channel >= 0 && channel < theMAD->header->numChn) z = channel;
  820.                         else DebugStr("\pOut - Channel");
  821.                         
  822.                         aCmd = GetMADCommand( Row, z, theMAD->partition[ i]);
  823.                         
  824.                         // PERIOD
  825.                         
  826.                         if( (tempChar & 32) != 0)
  827.                         {
  828.                             aCmd->note = theS3MCopy[ 0];
  829.                             
  830.                             Octave = (aCmd->note & 0xF0) >> 4;
  831.                             Note = (aCmd->note & 0x0F);
  832.                                 
  833.                             aCmd->note = Octave*12 + Note;
  834.                             if( aCmd->note < 0 || aCmd->note >= NUMBER_NOTES) aCmd->note = 0xFF;
  835.                             
  836.                             aCmd->ins = theS3MCopy[ 1];
  837.                         //    if( theMAD->instrument[ theS3MCopy[ 1] - 1] != 0) aCmd->InstrumentNo = theS3MCopy[ 1];
  838.                             
  839.                             theS3MCopy += 2L;
  840.                         }
  841.                         
  842.                         // VOLUME
  843.                         
  844.                         if( (tempChar & 64) != 0)
  845.                         {
  846.                             aCmd->vol = theS3MCopy[ 0];
  847.                             if( aCmd->vol > 64) aCmd->vol = 64;
  848.                             aCmd->vol += 0x10;
  849.                             
  850.                             theS3MCopy += 1L;
  851.                         }
  852.                         else aCmd->vol = 255;
  853.                         
  854.                         // PARAMETER
  855.                         
  856.                         if( (tempChar & 128) != 0)
  857.                         {
  858.                             if( theS3MCopy[ 0] != 255)
  859.                             {
  860.                                 ConvertS3MEffect( theS3MCopy[ 0], theS3MCopy[ 1], &aCmd->cmd, &aCmd->arg);
  861.                             }
  862.                             theS3MCopy += 2L;
  863.                         }
  864.                     }
  865.             }
  866.         }
  867.     }
  868.     
  869.     DisposPtr( (Ptr) s3minfo.orders);        DisposPtr( (Ptr) s3minfo.parapins);
  870.     DisposPtr( (Ptr) s3minfo.parappat);        DisposPtr( (Ptr) s3minfo.insdata);
  871.  
  872.     return noErr;
  873. }
  874.  
  875. OSErr ExtractS3MInfo( PPInfoRec *info, Ptr AlienFile)
  876. {
  877.     s3mform        *myS3M = ( s3mform*) AlienFile;
  878.     short        i;
  879.     short        maxInstru;
  880.     short        tracksNo;
  881.     s3mform        s3minfo;
  882.     /********************************/
  883.  
  884.     /**** Header principal *****/
  885.     BlockMove( AlienFile, &s3minfo, 96);
  886.     
  887.     /*** Signature ***/
  888.     
  889.     info->signature = 'S3M ';
  890.     
  891.     /*** Internal name ***/
  892.     
  893.     myS3M->name[ 27] = '\0';
  894.     pStrcpy( info->internalFileName, CtoPstr( myS3M->name));
  895.  
  896.     /*** Total Patterns ***/
  897.     
  898.     info->totalPatterns = 0;
  899.     
  900.     /*** Partition Length ***/
  901.     
  902.     info->partitionLength = 0;
  903.     
  904.     /*** Total Instruments ***/
  905.     
  906.     info->totalInstruments = Tdecode16(  &s3minfo.insnum);
  907.     
  908.     pStrcpy( info->formatDescription, "\pS3M Plug");
  909.  
  910.     return noErr;
  911. }
  912.  
  913. OSErr TestS3MFile( Ptr AlienFile)
  914. {
  915. s3mform    *myS3M = ( s3mform*) AlienFile;
  916.  
  917. if(    myS3M->s3msig[ 0] == 'S' &&
  918.     myS3M->s3msig[ 1] == 'C' &&
  919.     myS3M->s3msig[ 2] == 'R' &&
  920.     myS3M->s3msig[ 3] == 'M') return   noErr;
  921.     else return  MADFileNotSupportedByThisPlug;
  922. }
  923.  
  924. OSErr main( OSType order, FSSpec *AlienFileFSSpec, MADPartition *MadFile, PPInfoRec *info)
  925. {
  926.     OSErr    myErr;
  927.     Ptr        AlienFile;
  928.     short    vRefNum, iFileRefI;
  929.     long    dirID, sndSize;
  930.     
  931. #ifndef powerc
  932.     long    oldA4 = SetCurrentA4();             //this call is necessary for strings in 68k code resources
  933. #endif
  934.  
  935.     HGetVol( 0L, &vRefNum, &dirID);
  936.     HSetVol( 0L, AlienFileFSSpec->vRefNum, AlienFileFSSpec->parID);
  937.  
  938.     myErr = noErr;
  939.  
  940.     switch( order)
  941.     {
  942.         case 'EXPL':
  943.             AlienFile = ConvertMad2S3M( MadFile);
  944.             
  945.             if( AlienFile != 0L)
  946.             {
  947.                 myErr = FSOpen( AlienFileFSSpec->name, 0, &iFileRefI);
  948.                 if( myErr == fnfErr)
  949.                 {
  950.                     myErr = Create( AlienFileFSSpec->name, 0, 'SNPL', 'S3M ');
  951.                     myErr = FSOpen( AlienFileFSSpec->name, 0, &iFileRefI);
  952.                 }
  953.                 
  954.                 if( myErr == noErr)
  955.                 {
  956.                     FInfo    fndrInfo;
  957.                 
  958.                     sndSize = GetPtrSize( AlienFile);
  959.                     myErr = SetEOF( iFileRefI, sndSize);
  960.                     myErr = FSWrite( iFileRefI, &sndSize, AlienFile);
  961.                     FSClose( iFileRefI);
  962.                     
  963.                     GetFInfo( AlienFileFSSpec->name, 0, &fndrInfo);
  964.                     fndrInfo.fdCreator    = 'SNPL';
  965.                     fndrInfo.fdType        = 'S3M ';
  966.                     SetFInfo( AlienFileFSSpec->name, 0, &fndrInfo);
  967.                 }
  968.                 DisposPtr( AlienFile);    AlienFile = 0L;
  969.             }
  970.             else myErr = MADNeedMemory;
  971.         break;
  972.         
  973.         case 'IMPL':
  974.             myErr = FSOpen( AlienFileFSSpec->name, 0, &iFileRefI);
  975.             if( myErr == noErr)
  976.             {
  977.                 GetEOF( iFileRefI, &sndSize);
  978.             
  979.                 // ** MEMORY Test Start
  980.                 AlienFile = NewPtr( sndSize * 2L);
  981.                 if( AlienFile == 0L) myErr = MADNeedMemory;
  982.                 // ** MEMORY Test End
  983.                 
  984.                 else
  985.                 {
  986.                     DisposPtr( AlienFile);
  987.                     
  988.                     AlienFile = NewPtr( sndSize);
  989.                     myErr = FSRead( iFileRefI, &sndSize, AlienFile);
  990.                     if( myErr == noErr)
  991.                     {
  992.                         myErr = TestS3MFile( AlienFile);
  993.                         if( myErr == noErr)
  994.                         {
  995.                             myErr = ConvertS3M2Mad( AlienFile,  GetPtrSize( AlienFile), MadFile);
  996.                         }
  997.                     }
  998.                     DisposPtr( AlienFile);    AlienFile = 0L;
  999.                 }
  1000.                 FSClose( iFileRefI);
  1001.             }
  1002.         break;
  1003.         
  1004.         case 'TEST':
  1005.             myErr = FSOpen( AlienFileFSSpec->name, 0, &iFileRefI);
  1006.             if( myErr == noErr)
  1007.             {
  1008.                 sndSize = 1024L;
  1009.                 
  1010.                 AlienFile = NewPtr( sndSize);
  1011.                 if( AlienFile == 0L) myErr = MADNeedMemory;
  1012.                 else
  1013.                 {
  1014.                     myErr = FSRead( iFileRefI, &sndSize, AlienFile);
  1015.                     myErr = TestS3MFile( AlienFile);
  1016.                     
  1017.                     DisposPtr( AlienFile);    AlienFile = 0L;
  1018.                 }
  1019.                 FSClose( iFileRefI);
  1020.             }
  1021.         break;
  1022.  
  1023.         case 'INFO':
  1024.             myErr = FSOpen( AlienFileFSSpec->name, 0, &iFileRefI);
  1025.             if( myErr == noErr)
  1026.             {
  1027.                 GetEOF( iFileRefI, &info->fileSize);
  1028.             
  1029.                 sndSize = 5000L;    // Read only 5000 first bytes for optimisation
  1030.                 
  1031.                 AlienFile = NewPtr( sndSize);
  1032.                 if( AlienFile == 0L) myErr = MADNeedMemory;
  1033.                 else
  1034.                 {
  1035.                     myErr = FSRead( iFileRefI, &sndSize, AlienFile);
  1036.                     if( myErr == noErr)
  1037.                     {
  1038.                         myErr = ExtractS3MInfo( info, AlienFile);
  1039.                     }
  1040.                     DisposPtr( AlienFile);    AlienFile = 0L;
  1041.                 }
  1042.                 FSClose( iFileRefI);
  1043.             }
  1044.         break;
  1045.         
  1046.         default:
  1047.             myErr = MADOrderNotImplemented;
  1048.         break;
  1049.     }
  1050.  
  1051.     HSetVol( 0L, vRefNum, dirID);
  1052.  
  1053.     #ifndef powerc
  1054.         SetA4( oldA4);
  1055.     #endif
  1056.     return myErr;
  1057. }